package com.guqj.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NIOClient {

	/* 标识数字 */
	private static int flag = 0;
	/* 缓冲区大小 */
	private static int BLOCK = 4096;
	/* 接受数据缓冲区 */
	private static ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK);
	/* 发送数据缓冲区 */
	private static ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK);
	/* 服务器端地址 */
	private final static InetSocketAddress SERVER_ADDRESS = new InetSocketAddress("localhost", 11010);
	private Selector selector;
	
	public NIOClient() throws IOException {
		SocketChannel socketChannel = SocketChannel.open();
		socketChannel.configureBlocking(false);
		// 打开选择器
		selector = Selector.open();
		// 注册连接服务端socket动作
		socketChannel.register(selector, SelectionKey.OP_CONNECT);
		// 连接
		socketChannel.connect(SERVER_ADDRESS);
	}
	
	public void send() throws IOException{
		while(true){
			selector.select();
			Set<SelectionKey> selectionKeys = selector.selectedKeys();
			for(Iterator<SelectionKey> it = selectionKeys.iterator(); it.hasNext();){
				SelectionKey selectionKey = it.next();
				handleKey(selectionKey);
			}
		}
	}
	
	public void handleKey(SelectionKey selectionKey) throws IOException{
		SocketChannel client;  
        String receiveText;  
        String sendText;  
        int count=0;
        
		if(selectionKey.isConnectable()){
			System.out.println("client connect");
			client = (SocketChannel) selectionKey.channel();
			// 完成套接字通道的连接过程
			if(client.isConnectionPending()){
				client.finishConnect();  
                System.out.println("完成连接!"); 
                sendbuffer.clear();  
                sendbuffer.put("Hello,Server".getBytes());  
                sendbuffer.flip();  
                client.write(sendbuffer);
			}
			client.register(selector, SelectionKey.OP_READ);
		} else if(selectionKey.isReadable()){
			client = (SocketChannel) selectionKey.channel();
			receivebuffer.clear();
			// 读取服务器发送来的数据到缓冲区中
			count = client.read(receivebuffer);
			if (count > 0) {
				receiveText = new String(receivebuffer.array(), 0, count);
				System.out.println("客户端接受服务器端数据--:" + receiveText);
				client.register(selector, SelectionKey.OP_WRITE);
			}
		} else if(selectionKey.isWritable()){
			// 返回为之创建此键的通道。
			client = (SocketChannel) selectionKey.channel();
			sendbuffer.clear();
			sendText = "message from client--" + flag++;
			//向缓冲区中输入数据 
			sendbuffer.put(sendText.getBytes());
			//将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
			sendbuffer.flip();
			//输出到通道
			client.write(sendbuffer);
			System.out.println("客户端向服务器端发送数据--：" + sendText);
			client.register(selector, SelectionKey.OP_READ);
		}
	}
	
	public static void main(String[] args) throws IOException {
		NIOClient client = new NIOClient();
		client.send();
	}
}
